use std::{error::Error, fmt::Display};

pub const ERROR_PARSE: i32 = 1;
pub const ERROR_MESSAGE_SIZE_TOO_LARGE: i32 = 2;
pub const ERROR_INVALID_SUBJECT: i32 = 3;
pub const ERROR_SUBSCRIBTION_NOT_FOUND: i32 = 4;
pub const ERROR_CONNECTION_CLOSED: i32 = 5;
pub const ERROR_UNKOWN_ERROR: i32 = 1000;

pub type Result<T> = std::result::Result<T, NError>;

#[derive(Debug)]
pub struct NError {
    pub err_code: i32,
}

impl NError {
    #[inline]
    pub fn new(err_code: i32) -> Self {
        Self {err_code}
    }

    pub fn error_description(&self) -> &'static str {
        match self.err_code {
            ERROR_PARSE => "解析数据失败",
            ERROR_MESSAGE_SIZE_TOO_LARGE => "消息数据超出最大值",
            ERROR_INVALID_SUBJECT => "错误的主体",
            ERROR_SUBSCRIBTION_NOT_FOUND => "没有找到订阅信息",
            ERROR_CONNECTION_CLOSED => "远程连接关闭",
            ERROR_UNKOWN_ERROR => "未知错误",
            _ => "系统错误"
        }
    }
}

impl From<i32> for NError {
    #[inline]
    fn from(err_code: i32) -> Self {
        Self::new(err_code)
    }
}

impl Display for NError {

    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_fmt(format_args!("code = {}，description = {}", self.err_code, self.error_description()))
    }
}

impl Error for NError {
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn it_works() {
        let err = NError::from(5);
        println!("{}", err.to_string());
    }
}